/*
* @(#)Mailer.java
*
* Copyright (c) 2003 DCIVision Ltd
* All rights reserved.
*
* This software is the confidential and proprietary information of DCIVision
* Ltd ("Confidential Information").  You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the license
* agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.notification;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.Utility;

/**
 * <p>Class Name:       Mailer.java    </p>
 * <p>Description:      This class send email out through SMTP  </p>
 *
 * @author           Ryan Kwan
 * @company          DCIVision Limited
 * @creation date    26/01/2005
 * @version          $Revision: 1.7.2.3 $
 */

public class Mailer {

  public static final String REVISION = "$Revision: 1.7.2.3 $";

  private static final int DEFAULT_SMTP_PORT = 25;

  private Log log = LogFactory.getLog(this.getClass().getName());
  private boolean m_bDebug = false;

  public void setDebug(boolean debug){
    m_bDebug = debug;
  }

  public void sendEmail(EmailDeliveryMessage message) throws ApplicationException{
    List messages = new ArrayList();
    messages.add(message);
    sendEmail(messages);
  }

  public boolean sendEmail(List messages) throws ApplicationException {
    boolean returnValue = true;
    Transport transport = null;
    Session session = null;
    int port = DEFAULT_SMTP_PORT;
    EmailDeliveryMessage em = null;
    Properties prop = System.getProperties();
    prop.put("mail.smtp.host", SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_HOST));

    Authenticator authenticator = null;
    if(SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.SMTP_AUTH)){
      prop.put("mail.smtp.auth", "true");
      authenticator = new PasswordAuthenticator(SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_USERNAME),
                                                                              SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PASSWORD));
    }

    if (!Utility.isEmpty(SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PORT))) {
      port = Integer.parseInt(SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PORT).trim());
    }

    try {
      session = Session.getInstance(prop, authenticator);
      session.setDebug(m_bDebug);

      transport = session.getTransport("smtp");

      //------- Bug fix for bug 5954 by Ferdinand
      //-- This bug is due to invalid username and password
      //-- when we turn the smpt auth parameter off and set the username , password both to be empty in system parameter
      //-- The SystemParameterFactory will return empty string for both key , instead of NULL.
      //-- However, the Transport expect to receive NULL for both username and password
      
      //Create 2 temp String for processing the username and password
      String tmpUsername = null;
      String tmpPassword = null;
      
      //If the username/password is not empty string, store the value into the tmp variable
      if(!SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_USERNAME).equals("")){
        tmpUsername = SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_USERNAME);
      }      
      if(!SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PASSWORD).equals("")){
        tmpPassword = SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PASSWORD);
      }
      
      /*
      transport.connect(SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_HOST),
                        port,
                        SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_USERNAME),
                        SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_PASSWORD));
      */
      transport.connect(SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_HOST),
                        port,
                        tmpUsername,
                        tmpPassword);
      
      for (int i = 0; i < messages.size(); i++) {
        em = (EmailDeliveryMessage) messages.get(i);
        em.setSession(session);
        
        if(!em.getToRecipientList().toString().equals("[]")){
        log.debug("Sending email to : " + em.getToRecipientList());
        try{
        Transport.send((Message)em.getResolvedMessage());
        }catch (Exception e) {
          log.error("Error when sending email:", e);
          returnValue = false;
        }
        }else{
        	MimeMessage msg = (MimeMessage)em.getResolvedMessage();
        	if(!em.getCCRecipientList().toString().equals("[]")){
        	  log.debug("Sending email cc :"+em.getCCRecipientList());
        	  transport.sendMessage(msg,msg.getRecipients(Message.RecipientType.CC));	
        	}
        	if(!em.getBCCRecipientList().toString().equals("[]")){
        	  log.debug("Sending email bcc :"+em.getBCCRecipientList());
       	      transport.sendMessage(msg,msg.getRecipients(Message.RecipientType.BCC));		
        	}       
        }
      }
    } catch (MessagingException mx) {
      log.error("Fail to send email:" + mx.getMessage(), mx);
      throw new ApplicationException(DmsErrorConstant.ERROR_DMS_SEND_EMAIL,mx);
    }catch(Exception e){
      log.error(e, e);
    }
    finally {
      try{
        transport.close();
      } catch (MessagingException e) {
        log.error("Fail to close transport" + e.getMessage());
        //ignore
      }
    }
    return returnValue;
  }
}

class PasswordAuthenticator extends Authenticator
{
   String user;
   String pw;

   public PasswordAuthenticator (String username, String password)
   {
      super();
      this.user = username;
      this.pw = password;
   }
   public PasswordAuthentication getPasswordAuthentication()
   {
      return new PasswordAuthentication(user, pw);
   }
}

